package com.canaan.business.service.basic.impl;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.canaan.business.common.enums.productBom.BomStatusEnum;
import com.canaan.business.common.enums.productBom.BomTypeEnum;
import com.canaan.business.domain.basic.WmsProduct;
import com.canaan.business.domain.basic.WmsProductBom;
import com.canaan.business.domain.basic.WmsProductBomItem;
import com.canaan.business.domain.importEntity.ProductBomImportEntity;
import com.canaan.business.domain.vo.WmsProductBomExportVo;
import com.canaan.business.mapper.basic.WmsProductBomItemMapper;
import com.canaan.business.mapper.basic.WmsProductBomMapper;
import com.canaan.business.service.basic.IWmsProductBomService;
import com.canaan.business.service.basic.IWmsProductService;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.TableNoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.canaan.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

import static com.canaan.common.utils.SecurityUtils.getUsername;

/**
 * 物料BOM管理Service业务层处理
 *
 * @author ruoyi
 * @date 2023-01-28
 */
@Service
public class WmsProductBomServiceImpl implements IWmsProductBomService {

    private static final Logger log = LoggerFactory.getLogger(WmsProductBomServiceImpl.class);

    @Resource
    private WmsProductBomMapper wmsProductBomMapper;
    @Resource
    private WmsProductBomItemMapper wmsProductBomItemMapper;

    @Autowired
    private IWmsProductService wmsProductService;


    /**
     * 查询物料BOM管理
     *
     * @param id 物料BOM管理主键
     * @return 物料BOM管理
     */
    @Override
    public WmsProductBom selectWmsProductBomById(Long id) {
        return wmsProductBomMapper.selectWmsProductBomById(id);
    }

    /**
     * 查询物料BOM管理列表
     *
     * @param wmsProductBom 物料BOM管理
     * @return 物料BOM管理
     */
    @Override
    public List<WmsProductBom> selectWmsProductBomList(WmsProductBom wmsProductBom) {
        return wmsProductBomMapper.selectWmsProductBomList(wmsProductBom);
    }

    /**
     * 新增物料BOM管理
     *
     * @param wmsProductBom 物料BOM管理
     * @return 结果
     */
    @Override
    public int insertWmsProductBom(WmsProductBom wmsProductBom) {
        wmsProductBom.setCreateTime(DateUtils.getNowDate());
        // 需要校验，是否存在相同版本、BOM类型、物料的数据
        Integer oldBomNum = this.wmsProductBomMapper.checkBomNum(wmsProductBom.getProductNo(), wmsProductBom.getBomType(), wmsProductBom.getBomVersion(), null);
        if (oldBomNum > 0) {
            throw new ServiceException("该物料存在相同版本的物料BOM，请修改后提交");
        }
        wmsProductBom.setNo(TableNoUtil.getNo(WmsProductBom.class));
        wmsProductBom.setCreateBy(getUsername());
        wmsProductBom.setStatus(BomStatusEnum.NORMAL.getCode());
        return wmsProductBomMapper.insertWmsProductBom(wmsProductBom);
    }

    /**
     * 修改物料BOM管理
     *
     * @param wmsProductBom 物料BOM管理
     * @return 结果
     */
    @Override
    public int updateWmsProductBom(WmsProductBom wmsProductBom) {
        // 判断修改后的数据是否重复
        Integer oldBomNum = this.wmsProductBomMapper.checkBomNum(wmsProductBom.getProductNo(), wmsProductBom.getBomType(), wmsProductBom.getBomVersion(), wmsProductBom.getId());
        if (oldBomNum > 0) {
            throw new ServiceException("该物料存在相同版本的物料BOM，请修改后提交");
        }
        wmsProductBom.setUpdateTime(DateUtils.getNowDate());
        wmsProductBom.setUpdateBy(getUsername());
        return wmsProductBomMapper.updateWmsProductBom(wmsProductBom);
    }

    /**
     * 批量删除物料BOM管理
     *
     * @param nos 需要删除的物料BOM管理主键
     * @return 结果
     */
    @Override
    public int deleteWmsProductBomByNos(String[] nos) {
        // 需要同时删除BOM明细
        this.wmsProductBomMapper.removeBomItemByBomNos(nos);
        return wmsProductBomMapper.deleteWmsProductBomByNos(nos);
    }


    /**
     * 取消物料BOM
     *
     * @param id 需要取消的物料BOM管理id
     */
    @Override
    public void cancelBom(Long id) {
        WmsProductBom cancelBomEntity = this.selectWmsProductBomById(id);
        cancelBomEntity.setStatus(BomStatusEnum.SCRAP.getCode());
        this.updateWmsProductBom(cancelBomEntity);
    }

    /**
     * 删除物料BOM管理信息
     *
     * @param id 物料BOM管理主键
     * @return 结果
     */
    @Override
    public int deleteWmsProductBomById(Long id) {
        return wmsProductBomMapper.deleteWmsProductBomById(id);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importBom(List<ProductBomImportEntity> fileDataList) {
        if (StringUtils.isNull(fileDataList) || fileDataList.size() == 0) {
            throw new ServiceException("导入物料BOM数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        List<String> fileProductNos = new ArrayList<>();
        List<String> fileMainNos = new ArrayList<>();
        // 循环校验必填
        for (int i = 0; i < fileDataList.size(); i++) {
            ProductBomImportEntity fileEntity = fileDataList.get(i);
            int rowNum = i + 2;
            if (StringUtils.isEmpty(fileEntity.getMainProductNo())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行主物料编码不能为空");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getBomVersion())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行BOM版本不能为空");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getBomType())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行BOM类型不能为空");
                break;
            }else if (StringUtils.isEmpty(BomTypeEnum.getCodeByMessage(fileEntity.getBomType()))){
                failureNum++;
                failureMsg.append("第" + rowNum + "行BOM类型输入有误");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getSonProductNo())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行子物料编码不能为空");
                break;
            }
            if (fileEntity.getQuantity() == null) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行数量不能为空");
                break;
            }
            if (!fileProductNos.contains(fileEntity.getMainProductNo())) {
                fileProductNos.add(fileEntity.getMainProductNo());
                fileMainNos.add(fileEntity.getMainProductNo());
            }
            if (!fileProductNos.contains(fileEntity.getSonProductNo())) {
                fileProductNos.add(fileEntity.getSonProductNo());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException(failureMsg.toString());
        }
        WmsProduct searchWmsProduct = new WmsProduct();
        searchWmsProduct.setProductNos(fileProductNos);
        // 查询文档中存在的所有物料
        List<WmsProduct> allProductList = this.wmsProductService.selectWmsProductList(searchWmsProduct);
        // key:物料编号  value:实体类
        Map<String, WmsProduct> productMap = allProductList.stream().collect(Collectors.toMap(WmsProduct::getProductNo, Function.identity(), (key1, key2) -> key2));
        // 查询已存在的所有物料BOM，用于校验是否BOM已经存在
        WmsProductBom searchBomParam = new WmsProductBom();
        searchBomParam.setProductNos(fileMainNos);
        List<WmsProductBom> fileProductBomList = this.selectWmsProductBomList(searchBomParam);
        // 物料编号 + BOM版本 + BOM类型,用于校验文档导入的数据是否已经存在
        List<String> checkBomList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fileProductBomList)){
            for (WmsProductBom wmsProductBom : fileProductBomList) {
                checkBomList.add(wmsProductBom.getProductNo() + wmsProductBom.getBomVersion() + wmsProductBom.getBomType());
            }
        }
        // key:物料编号 + BOM版本 + BOM类型  value:文档行实体类
        Map<String, List<ProductBomImportEntity>> bomGroupMap = new HashMap<>();
        // 循环判断物料是否存在，并将数据按主物料编码、BOM版本、BOM类型相同的分组
        for (int i = 0; i < fileDataList.size(); i++) {
            ProductBomImportEntity fileEntity = fileDataList.get(i);
            int rowNum = i + 2;
            try {
                // 物料编号验证是否存在物料
                WmsProduct mainProduct = productMap.get(fileEntity.getMainProductNo());
                WmsProduct sonProduct = productMap.get(fileEntity.getSonProductNo());

                if (StringUtils.isNull(mainProduct)) {
                    failureNum++;
                    failureMsg.append("第" + rowNum + "行主物料编号 " + fileEntity.getMainProductNo() + " 在系统中不存在");
                    break;
                }
                if (StringUtils.isNull(sonProduct)) {
                    failureNum++;
                    failureMsg.append("第" + rowNum + "行子物料编号 " + fileEntity.getSonProductNo() + " 在系统中不存在");
                    break;
                }
                String key = fileEntity.getMainProductNo() + fileEntity.getBomVersion() + BomTypeEnum.getCodeByMessage(fileEntity.getBomType());
                if (checkBomList.contains(key)){
                    failureNum++;
                    failureMsg.append("第" + rowNum + "行物料BOM已存在，请修改");
                    break;
                }
                List<ProductBomImportEntity> groupList = bomGroupMap.get(key);
                if (CollectionUtils.isEmpty(groupList)) {
                    groupList = new ArrayList<>();
                    groupList.add(fileEntity);
                    bomGroupMap.putIfAbsent(key, groupList);
                }
                // 如果已经存在，在原列表上新增
                else {
                    groupList.add(fileEntity);
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/> 第" + rowNum + "行数据有误，导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
                break;
            }
        }
        String createUserBy = getUsername();
        List<WmsProductBom> addBomList = new ArrayList<>();
        List<WmsProductBomItem> addBomItemList = new ArrayList<>();
        // 循环map组装需要插入的数据
        bomGroupMap.forEach((key, bomList) -> {
            WmsProductBom wmsProductBom = new WmsProductBom();
            wmsProductBom.setNo(TableNoUtil.getNo(WmsProductBom.class));
            wmsProductBom.setCreateBy(createUserBy);
            wmsProductBom.setCreateTime(new Date());
            wmsProductBom.setProductNo(bomList.get(0).getMainProductNo());
            WmsProduct mainProduct = productMap.get(wmsProductBom.getProductNo());
            wmsProductBom.setProductName(mainProduct.getProductName());
            wmsProductBom.setProductType(mainProduct.getProductType());
            wmsProductBom.setBomVersion(bomList.get(0).getBomVersion());
            wmsProductBom.setBomType(BomTypeEnum.getCodeByMessage(bomList.get(0).getBomType()));
            wmsProductBom.setStatus(BomStatusEnum.NORMAL.getCode());
            addBomList.add(wmsProductBom);
            // 循环生成BOM组件的数据
            for (ProductBomImportEntity productBomImportEntity : bomList) {
                WmsProduct sonProduct = productMap.get(productBomImportEntity.getSonProductNo());
                WmsProductBomItem wmsProductBomItem = new WmsProductBomItem();
                wmsProductBomItem.setNo(TableNoUtil.getNo(WmsProductBomItem.class));
                wmsProductBomItem.setBomNo(wmsProductBom.getNo());
                wmsProductBomItem.setCreateBy(createUserBy);
                wmsProductBomItem.setCreateTime(new Date());
                wmsProductBomItem.setProductNo(productBomImportEntity.getSonProductNo());
                wmsProductBomItem.setProductName(sonProduct.getProductName());
                wmsProductBomItem.setProductType(sonProduct.getProductType());
                wmsProductBomItem.setQuantity(productBomImportEntity.getQuantity());
                wmsProductBomItem.setProductUnit(productBomImportEntity.getProductUnit());
                addBomItemList.add(wmsProductBomItem);
            }
        });
        if (!CollectionUtils.isEmpty(addBomList)){
            this.wmsProductBomMapper.batchSave(addBomList);
        }
        if (!CollectionUtils.isEmpty(addBomItemList)){
            this.wmsProductBomItemMapper.batchSave(addBomItemList);
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException(failureMsg.toString());
        } else {
            int addCount = addBomList.size();
            successMsg.insert(0, "导入成功！共新增 " + addCount + " 条数据");
        }
        return successMsg.toString();
    }

    @Override
    public List<WmsProductBomExportVo> exportList(WmsProductBom wmsProductBom){
        List<WmsProductBomExportVo> voList = this.wmsProductBomMapper.exportList(wmsProductBom);
        return voList;
    }
}
